#include "Map.h"

#include <sstream>
#include <fstream>
#include <iostream>
#include "cstdio"

Map::Map(string mapName, string fileName){
	
	mName = mapName;
	MapTime = 600;
	std::ifstream infile(fileName);
	mIsReady = true;
	string str;
	STATUS mStatus = Map::BACK;
	mTree = new TreeNode();
	mBackTree = new TreeNode();
	mContainer.left = std::numeric_limits<long>::infinity();
	mContainer.right = -std::numeric_limits<long>::infinity();
	mContainer.top = -std::numeric_limits<long>::infinity();
	mContainer.bottom = std::numeric_limits<long>::infinity();
	try
	{
		int posx, posy, id, info,hashid;
		while(std::getline(infile,str)){

			if(str == "END"){
				mStatus = Map::CHOSED;
				continue;
			}

			if(str == "QUAD_BACK"){
				mStatus = Map::QUAD_BACK;
				continue;
			}

			if(str == "QUAD_CHOSED"){
				mStatus = Map::QUAD_CHOSED;
				continue;
			}

			if(str == "MAP_TIME"){
				mStatus = Map::MAP_TIME;
				continue;
			}

			if(str == "MAP_NAME"){
				mStatus = Map::MAP_NAME;
				continue;
			}

			std::stringstream iss(str);
			if(mStatus == Map::BACK){
				if(iss >> posx >> posy >> id >> info>>hashid){
					ObObject* temp = getObjectFromID(id);
					if(temp != 0){
						D3DXVECTOR3 pos = D3DXVECTOR3((float)posx,(float)posy,0);
						temp->setPos(pos);
						temp->setInfo(info);
						temp->setHashId(hashid);
						mBackMap.push_back(temp);
					}
					
				}
			}else if(mStatus == Map::CHOSED){
				if(iss >> posx >> posy >> id >> info >> hashid){
					ObObject* temp = getObjectFromID(id);
					if(temp != 0){
						D3DXVECTOR3 pos = D3DXVECTOR3((float)posx,(float)posy,0.0f);
						temp->setPos(pos);
						temp->setInfo(info);
						temp->setHashId(hashid);
						if(temp->getId()== ObPlayer::MARIO){
							mMario = temp;
						}else{
							mChosedMap.push_back(temp);
						}

						//get biggest rect for camera
						if(mContainer.left > pos.x){
							mContainer.left = (LONG)pos.x;
						}

						if(mContainer.right < pos.x + temp->getWidth()){
							mContainer.right = (LONG)pos.x;
						}

						if(mContainer.bottom > pos.y){
							mContainer.bottom = (LONG)pos.y;
						}

						if(mContainer.top < pos.y + temp->getHeight()){
							mContainer.top = (LONG)pos.y;
						}
					}
				}
			}else if(mStatus == Map::QUAD_BACK){
				int value;
				vector<int> countvector;
				while(iss>>value){
					countvector.push_back(value);
				}
				mBackTree->addNode(countvector,mBackMap, countvector[0]);
			}else if (mStatus == Map::QUAD_CHOSED){
				int value;
				vector<int> countvector;
				while(iss>>value){
					countvector.push_back(value);
				}
				mTree->addNode(countvector, mChosedMap, countvector[0]);
			}else if(mStatus == Map::MAP_TIME){
				iss>>MapTime;
			}else if(mStatus == Map::MAP_NAME){
				mName = str;
			}
		}
	}
	catch (int)
	{
		mIsReady = false;
	}
	
}

ObObject* Map::getObjectFromID(int id){
	ObObject* temp;
	//====================================
	if(ObBrick::checkType(id)){
		temp = new ObBrick();
		temp->setId(id);
		return temp;
	}

	if(ObBrickSP::checkType(id)){
		temp = new ObBrickSP();
		temp->setId(id);
		return temp;
	}

	if(ObPipe::checkType(id)){
		temp = new ObPipe();
		temp->setId(id);
		return temp;
	}

	if(ObCoin::checkType(id)){
		temp = new ObCoin();
		temp->setId(id);
		return temp;
	}

	if(ObDeathField::checkType(id)){
		temp = new ObDeathField();
		temp->setId(id);
		return temp;
	}

	if(ObScoreTree::checkType(id)){
		temp = new ObScoreTree();
		temp->setId(id);
		return temp;
	}

	//====================================
	if(ObCastle::checkType(id)){
		temp = new ObCastle();
		temp->setId(id);
		return temp;
	}

	if(ObCloud::checkType(id)){
		temp = new ObCloud();
		temp->setId(id);
		return temp;
	}

	if(ObGrass::checkType(id)){
		temp = new ObGrass();
		temp->setId(id);
		return temp;
	}

	if(ObMountain::checkType(id)){
		temp = new ObMountain();
		temp->setId(id);
		return temp;
	}

	if(ObBlackGround::checkType(id)){
		temp = new ObBlackGround();
		temp->setId(id);
		return temp;
	}

	//====================================
	if(EMushRoom::checkType(id)){
		temp = new EMushRoom();
		temp->setId(id);
		return temp;
	}

	if(ETurtle::checkType(id)){
		temp = new ETurtle();
		temp->setId(id);
		return temp;
	}

	if(ObPlayer::checkType(id)){
		temp = new ObPlayer();
		temp->setId(id);
		return temp;
	}
	//====================================
	return NULL;
}

Map::~Map(){
	while(!mChosedMap.empty()) delete mChosedMap.back(), mChosedMap.pop_back();
	while(!mBackMap.empty()) delete mBackMap.back(), mBackMap.pop_back();
	mChosedMap.clear();
	mBackMap.clear();

	delete mTree;
	delete mBackTree;
	delete mMario;
}

std::string Map::getName(){
	return mName;
}

std::vector<ObObject*> Map::getChosedMap(){
	return mChosedMap;
}

std::vector<ObObject*> Map::getBackMap(){
	return mBackMap;
}

TreeNode* Map::getChosedTree(){
	return mTree;
}

ObObject* Map::getMario(){
	return mMario;
}

TreeNode* Map::getBackTree(){
	return mBackTree;
}
